﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AgileFx.ORM.Materialization;
using System.Linq.Expressions;

using AgileFx.ORM;
using AgileFx.ORM.Backends.LinqToSql;
using AgileFx.ORM.QueryAnalysis;
using AgileFx.ORM.Utils;

namespace AgileFx.MVC.PerformanceTools
{
    public class TracingSingleObjectMaterializer<T> : SingleObjectMaterializer<T>
    {
        public TracingSingleObjectMaterializer(EntityContext context)
            : base(context)
        { }

        public override T GetResult(Expression expression)
        {
            var visitor = new QueryTranslationVisitor(new QueryAnalysisContext(entityContext._InternalServices.TypeTranslationUtil) { ModifyProjection = true });
            var translationResults = visitor.GetTranslatedResults(expression);

            var tableEntityQuery = translationResults.AnalysisContext.RootEntityQuery.TableEntityQuery;
            var tableEntity = tableEntityQuery.Provider.Execute(translationResults.TranslatedExpression);

            Guid guid = Guid.NewGuid();
            PerformanceSpy.TraceContext.WriteToLog("BEGIN SINGLE OBJECT MATERIALIZATION", guid.ToString());
            var result = base.GetResult(expression);
            PerformanceSpy.TraceContext.WriteToLog("END SINGLE OBJECT MATERIALIZATION", guid.ToString());

            try
            {   
                var l2sDataContext = (entityContext._InternalServices.TableEntityContext as DataContextWrapper).LinqToSqlContext;
                var commandText = l2sDataContext.GetCommand(tableEntityQuery).CommandText;
                PerformanceSpy.TraceContext.WriteToLog("SQL", commandText);
            }
            catch
            {
                PerformanceSpy.TraceContext.WriteToLog("SQL", "Failed to get Sql for IQueryProvider.Execute.");
            }

            if (TypesUtil.IsPrimitiveDataType(typeof(T)))
                return (T)tableEntity;
            else
                return MakeResult(tableEntity, translationResults.AnalysisContext.QueryableType);
        }
    }
}
